package com.heimdallr.rbac.permission.dao.impl;

import com.heimdallr.rbac.permission.dao.PermissionDao;
import com.heimdallr.rbac.permission.entity.*;
import com.heimdallr.util.AppUtils;
import com.heimdallr.util.RedisKey;
import com.heimdallr.util.SerializationUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @author user
 */
@Repository(value="permissionDao")
public class PermissionDaoImpl implements PermissionDao {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /** for permission page **/

    @Override
    public List<PermissionEntity> getPermissionListForPage(Map<String, String> paraMap){

        String permissionName =  paraMap.get("permissionName");
        String url =  paraMap.get("url");
        String mapping =  paraMap.get("mapping");

        List<PermissionEntity> result = getAllPermissionEntity();

        if(AppUtils.isNotNull(permissionName)){
            result = result.stream().filter(fi->fi.getName().startsWith(permissionName)).collect(Collectors.toList());
        }

        if(AppUtils.isNotNull(url)){
            result = result.stream().filter(fi->fi.getUrl().startsWith(url)).collect(Collectors.toList());
        }

        if(AppUtils.isNotNull(mapping)){
            result = result.stream().filter(fi->fi.getMapping().startsWith(mapping)).collect(Collectors.toList());
        }

        return result;
    }


    @Override
    public boolean savePermissionEntity(PermissionEntity entity){

        try {
            String redisStr =  new String(SerializationUtils.jdkserialize(entity),SerializationUtils.charsetCode);
            redisTemplate.opsForHash().put(RedisKey.permissionEntity.name(),entity.getId()+"",redisStr);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /** for role page **/
    @Override
    public List<RoleEntity> getRoleListForPage(Map<String, String> paraMap){

        String roleName =  paraMap.get("roleName");

        List<RoleEntity> result = getAllRoles();

        if(AppUtils.isNotNull(roleName)){
            result = result.stream().filter(fi->fi.getRoleName().startsWith(roleName)).collect(Collectors.toList());
        }

        return result;
    }

    /********else**********/

    @Override
    public RoleEntity getRoleEntityById(int id){

        RoleEntity roleEntity = null;

        if(redisTemplate.opsForHash().hasKey(RedisKey.roleEntity.name(),id+"")){

            String cache = (String) redisTemplate.opsForHash().get(RedisKey.roleEntity.name(),id+"");

            try {
                roleEntity = (RoleEntity) SerializationUtils.jdkdeserialize(cache.getBytes(SerializationUtils.charsetCode));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

        }

        List<PermissionEntity> permissionEntityList = new ArrayList<>();
        List<MenuEntity> menuEntityList = new ArrayList<>();

        roleEntity.getPermissionIds().forEach(permissionId->{
            PermissionEntity permissionEntity = getPermissionEntityById(permissionId);
            permissionEntityList.add(permissionEntity);
        });

        roleEntity.getMenuIds().forEach(menuId->{
            MenuEntity menuEntity = getMenuEntityById(menuId);
            menuEntityList.add(menuEntity);
        });

        roleEntity.setMenuEntityList(menuEntityList);
        roleEntity.setPermissionEntityList(permissionEntityList);

        return roleEntity;
    }

    @Override
    public boolean saveRoleEntity(RoleEntity entity){

        try {
            String redisStr =  new String(SerializationUtils.jdkserialize(entity),SerializationUtils.charsetCode);
            redisTemplate.opsForHash().put(RedisKey.roleEntity.name(),entity.getId()+"",redisStr);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public boolean saveGroupEntity(GroupEntity entity){

        try {
            String redisStr =  new String(SerializationUtils.jdkserialize(entity),SerializationUtils.charsetCode);
            redisTemplate.opsForHash().put(RedisKey.groupEntity.name(),entity.getId()+"",redisStr);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }



    @Override
    public PermissionEntity getPermissionEntityById(int id){

        PermissionEntity entity = null;

        if(redisTemplate.opsForHash().hasKey(RedisKey.permissionEntity.name(),id+"")){

            String cache = (String) redisTemplate.opsForHash().get(RedisKey.permissionEntity.name(),id+"");

            try {
                entity = (PermissionEntity) SerializationUtils.jdkdeserialize(cache.getBytes(SerializationUtils.charsetCode));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

        }

        return entity;
    }


    @Override
    public List<PermissionEntity> getAllPermissionEntity(){

        List<Object> redisResult = redisTemplate.opsForHash().values(RedisKey.permissionEntity.name());

        List<PermissionEntity> result = new ArrayList<>();

        for(Object redisStr : redisResult){

            PermissionEntity entity = null;

            try {
                entity = (PermissionEntity) SerializationUtils.jdkdeserialize(redisStr.toString().getBytes(SerializationUtils.charsetCode));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            if(entity!=null){
                result.add(entity);
            }

        }//end foreach

        if(result!=null&&!result.isEmpty()){
            result.sort(Comparator.comparing(PermissionEntity::getName));
        }

        return result;
    }


    /**
     * for webapp init
     * @return
     */
    @Override
    public List<RoleEntity> getAllRoles(){
        List<Object> redisResult = redisTemplate.opsForHash().values(RedisKey.roleEntity.name());

        List<RoleEntity> result = new ArrayList<>();

        for(Object redisStr : redisResult){

            RoleEntity entity = null;

            try {
                entity = (RoleEntity) SerializationUtils.jdkdeserialize(redisStr.toString().getBytes(SerializationUtils.charsetCode));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            if(entity!=null){
                result.add(entity);
            }

        }//end foreach

        return result;
    }


    /***menu ***/

    @Override
    public MenuEntity getMenuEntityById(int id) {

        MenuEntity entity = null;

        if(redisTemplate.opsForHash().hasKey(RedisKey.menuEntity.name(),id+"")){

            String cache = (String) redisTemplate.opsForHash().get(RedisKey.menuEntity.name(),id+"");

            try {
                entity = (MenuEntity) SerializationUtils.jdkdeserialize(cache.getBytes(SerializationUtils.charsetCode));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

        }

        return entity;
    }


	@Override
	public List<MenuEntity> getAllMenuList() {

        List<Object> redisResult = redisTemplate.opsForHash().values(RedisKey.menuEntity.name());

        List<MenuEntity> result = new ArrayList<>();

        for(Object redisStr : redisResult){

            MenuEntity entity = null;

            try {
                entity = (MenuEntity) SerializationUtils.jdkdeserialize(redisStr.toString().getBytes(SerializationUtils.charsetCode));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            if(entity!=null){
                result.add(entity);
            }

        }//end foreach

        return result;
	}


    @Override
    public boolean saveMenuEntity(MenuEntity entity){

        try {
            String redisStr =  new String(SerializationUtils.jdkserialize(entity),SerializationUtils.charsetCode);
            redisTemplate.opsForHash().put(RedisKey.menuEntity.name(),entity.getId()+"",redisStr);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
	
}
